local Gladius = _G.Gladius
if not Gladius then
	DEFAULT_CHAT_FRAME:AddMessage(format("Module %s requires Gladius", "Trinket"))
end
local L = Gladius.L
local LSM

-- global functions
local strfind = string.find
local pairs = pairs
local strformat = string.format
local UnitName, UnitClass, UnitFactionGroup, UnitLevel = UnitName, UnitClass, UnitFactionGroup, UnitLevel

local Trinket = Gladius:NewModule("Trinket", false, true, {
	trinketAttachTo = "Frame",
	trinketAnchor = "TOPLEFT",
	trinketRelativePoint = "TOPRIGHT",
	trinketGridStyleIcon = false,
	trinketGridStyleIconColor = {r = 0, g = 1, b = 0, a = 1},
	trinketGridStyleIconUsedColor = {r = 1, g = 0, b = 0, a = 1},
	trinketAdjustSize = true,
	trinketSize = 52,
	trinketOffsetX = 1,
	trinketOffsetY = 0,
	trinketFrameLevel = 2,
	trinketIconCrop = false,
	trinketGloss = true,
	trinketGlossColor = {r = 1, g = 1, b = 1, a = 0.4},
	trinketCooldown = true,
	trinketCooldownReverse = false,
	trinketFaction = true,
},
{
	"Trinket icon", "Grid style health bar", "Grid style power bar"
})

function Trinket:OnEnable()
	self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
	LSM = Gladius.LSM
	if (not self.frame) then
		self.frame = { }
	end 
end

function Trinket:OnDisable()
	self:UnregisterAllEvents()
	for unit in pairs(self.frame) do
		self.frame[unit]:SetAlpha(0)
	end
end

function Trinket:GetAttachTo()
	return Gladius.db.trinketAttachTo
end

function Trinket:GetFrame(unit)
	return self.frame[unit]
end

function Trinket:SetTemplate(template)
	if (template == 1) then
	-- reset width
		if (Gladius.db.targetBarAttachTo == "HealthBar" and not Gladius.db.healthBarAdjustWidth) then
			Gladius.db.healthBarAdjustWidth = true
		end
		-- reset to default
		for k, v in pairs(self.defaults) do
			Gladius.db[k] = v
		end
	elseif (template == 2) then
		if (Gladius.db.modules["HealthBar"]) then
			if (Gladius.db.healthBarAdjustWidth) then
				Gladius.db.healthBarAdjustWidth = false
				Gladius.db.healthBarWidth = Gladius.db.barWidth - Gladius.db.healthBarHeight
			else
				Gladius.db.healthBarWidth = Gladius.db.healthBarWidth - Gladius.db.healthBarHeight
			end
			Gladius.db.trinketGridStyleIcon = true
			Gladius.db.trinketAdjustHeight = false
			Gladius.db.trinketHeight = Gladius.db.healthBarHeight
			Gladius.db.trinketAttachTo = "HealthBar"
			Gladius.db.trinketAnchor = "TOPLEFT"
			Gladius.db.trinketRelativePoint = "TOPRIGHT"
			Gladius.db.trinketOffsetX = 0
			Gladius.db.trinketOffsetY = 0
		end
	else
		if (Gladius.db.modules["PowerBar"]) then
			if (Gladius.db.powerBarAdjustWidth) then
				Gladius.db.powerBarAdjustWidth = false
				Gladius.db.powerBarWidth = Gladius.db.powerBarWidth - Gladius.db.powerBarHeight
			else
				Gladius.db.powerBarWidth = Gladius.db.powerBarWidth - Gladius.db.powerBarHeight
			end
			Gladius.db.trinketGridStyleIcon = true
			Gladius.db.trinketAdjustHeight = false
			Gladius.db.trinketHeight = Gladius.db.powerBarHeight
			Gladius.db.trinketAttachTo = "PowerBar"
			Gladius.db.trinketAnchor = "TOPLEFT"
			Gladius.db.trinketRelativePoint = "TOPRIGHT"
			Gladius.db.trinketOffsetX = 0
			Gladius.db.trinketOffsetY = 0
		end
	end
end

function Trinket:UNIT_SPELLCAST_SUCCEEDED(event, unit, spell, rank)
	if (not strfind(unit, "arena") or strfind(unit, "pet")) then
		return
	end
	-- pvp trinket
	if (spell == GetSpellInfo(59752) or spell == GetSpellInfo(42292)) then
		self:UpdateTrinket(unit, 120)
	end
	-- wotf
	if (spell == GetSpellInfo(7744)) then
		self:UpdateTrinket(unit, 45)
	end
end

function Trinket:UpdateTrinket(unit, duration)
	-- grid style icon
	if (Gladius.db.trinketGridStyleIcon) then
		self.frame[unit].texture:SetVertexColor(Gladius.db.trinketGridStyleIconUsedColor.r, Gladius.db.trinketGridStyleIconUsedColor.g, Gladius.db.trinketGridStyleIconUsedColor.b, Gladius.db.trinketGridStyleIconUsedColor.a)
	end
	-- announcement
	if (Gladius.db.announcements.trinket) then
	Gladius:Call(Gladius.modules.Announcements, "Send", strformat(L["TRINKET USED: %s (%s)"], UnitName(unit) or "test", UnitClass(unit) or "test"), 2, unit)
	end
	if (Gladius.db.announcements.trinket or Gladius.db.trinketGridStyleIcon) then
		self.frame[unit].timeleft = duration
		self.frame[unit]:SetScript("OnUpdate", function(f, elapsed)
			self.frame[unit].timeleft = self.frame[unit].timeleft - elapsed
			if (self.frame[unit].timeleft <= 0) then
			-- trinket
				if (Gladius.db.trinketGridStyleIcon) then
					self.frame[unit].texture:SetVertexColor(Gladius.db.trinketGridStyleIconColor.r, Gladius.db.trinketGridStyleIconColor.g, Gladius.db.trinketGridStyleIconColor.b, Gladius.db.trinketGridStyleIconColor.a)
				end
				-- announcement
				if (Gladius.db.announcements.trinket) then
					Gladius:Call(Gladius.modules.Announcements, "Send", strformat(L["TRINKET READY: %s (%s)"], UnitName(unit) or "", UnitClass(unit) or ""), 2, unit)
				end
				self.frame[unit]:SetScript("OnUpdate", nil)
			end
		end)
	end
	-- cooldown
	Gladius:Call(Gladius.modules.Timer, "SetTimer", self.frame[unit], duration)
end

function Trinket:CreateFrame(unit)
	local button = Gladius.buttons[unit]
	if (not button) then
		return
	end
	-- create frame
	self.frame[unit] = CreateFrame("CheckButton", "Gladius"..self.name.."Frame"..unit, button, "ActionButtonTemplate")
	self.frame[unit]:EnableMouse(false)
	self.frame[unit]:SetNormalTexture("Interface\\AddOns\\Gladius\\Images\\Gloss")
	self.frame[unit].texture = _G[self.frame[unit]:GetName().."Icon"]
	self.frame[unit].normalTexture = _G[self.frame[unit]:GetName().."NormalTexture"]
	self.frame[unit].cooldown = _G[self.frame[unit]:GetName().."Cooldown"]
end

function Trinket:Update(unit)
	-- create frame
	if (not self.frame[unit]) then
		self:CreateFrame(unit)
	end
	-- update frame
	self.frame[unit]:ClearAllPoints()
	-- anchor point 
	local parent = Gladius:GetParent(unit, Gladius.db.trinketAttachTo)
	self.frame[unit]:SetPoint(Gladius.db.trinketAnchor, parent, Gladius.db.trinketRelativePoint, Gladius.db.trinketOffsetX, Gladius.db.trinketOffsetY)
	-- frame level
	self.frame[unit]:SetFrameLevel(Gladius.db.trinketFrameLevel)
	if (Gladius.db.trinketAdjustSize) then
		if (self:GetAttachTo() == "Frame") then
			local height = false
			-- need to rethink that
			--[[for _, module in pairs(Gladius.modules) do
				if (module:GetAttachTo() == self.name) then
					height = false
				end
			end]]
			if (height) then
			self.frame[unit]:SetWidth(Gladius.buttons[unit].height)
			self.frame[unit]:SetHeight(Gladius.buttons[unit].height)
			else
			self.frame[unit]:SetWidth(Gladius.buttons[unit].frameHeight)
			self.frame[unit]:SetHeight(Gladius.buttons[unit].frameHeight)
			end
		else
			self.frame[unit]:SetWidth(Gladius:GetModule(self:GetAttachTo()).frame[unit]:GetHeight() or 1)
			self.frame[unit]:SetHeight(Gladius:GetModule(self:GetAttachTo()).frame[unit]:GetHeight() or 1)
		end
	else
		self.frame[unit]:SetWidth(Gladius.db.trinketSize)
		self.frame[unit]:SetHeight(Gladius.db.trinketSize)
	end
	-- set frame mouse-interactable area
	if (self:GetAttachTo() == "Frame") then
		local left, right, top, bottom = Gladius.buttons[unit]:GetHitRectInsets()
		if (strfind(Gladius.db.trinketRelativePoint, "LEFT")) then
			left = - self.frame[unit]:GetWidth() + Gladius.db.trinketOffsetX
		else
			right = - self.frame[unit]:GetWidth() + - Gladius.db.trinketOffsetX
		end
		-- search for an attached frame
		--[[for _, module in pairs(Gladius.modules) do
			if (module.attachTo and module:GetAttachTo() == self.name and module.frame and module.frame[unit]) then
				local attachedPoint = module.frame[unit]:GetPoint()
				if (strfind(Gladius.db.trinketRelativePoint, "LEFT") and (not attachedPoint or (attachedPoint and strfind(attachedPoint, "RIGHT")))) then
					left = left - module.frame[unit]:GetWidth()
				elseif (strfind(Gladius.db.trinketRelativePoint, "RIGHT") and (not attachedPoint or (attachedPoint and strfind(attachedPoint, "LEFT")))) then
					right = right - module.frame[unit]:GetWidth()
				end
			end
		end]]
		-- top / bottom
		if (self.frame[unit]:GetHeight() > Gladius.buttons[unit]:GetHeight()) then
			bottom = -(self.frame[unit]:GetHeight() - Gladius.buttons[unit]:GetHeight()) + Gladius.db.trinketOffsetY
		end
		Gladius.buttons[unit]:SetHitRectInsets(left, right, 0, 0)
		Gladius.buttons[unit].secure:SetHitRectInsets(left, right, 0, 0)
	end
	-- style action button
	self.frame[unit].normalTexture:SetHeight(self.frame[unit]:GetHeight() + self.frame[unit]:GetHeight() * 0.4)
	self.frame[unit].normalTexture:SetWidth(self.frame[unit]:GetWidth() + self.frame[unit]:GetWidth() * 0.4)
	self.frame[unit].normalTexture:ClearAllPoints()
	self.frame[unit].normalTexture:SetPoint("CENTER", 0, 0)
	self.frame[unit]:SetNormalTexture("Interface\\AddOns\\Gladius\\Images\\Gloss")
	self.frame[unit].texture:ClearAllPoints()
	self.frame[unit].texture:SetPoint("TOPLEFT", self.frame[unit], "TOPLEFT")
	self.frame[unit].texture:SetPoint("BOTTOMRIGHT", self.frame[unit], "BOTTOMRIGHT")
	if (not Gladius.db.trinketIconCrop and not Gladius.db.trinketGridStyleIcon) then
		self.frame[unit].texture:SetTexCoord(0, 1, 0, 1)
	else
		self.frame[unit].texture:SetTexCoord(0.07, 0.93, 0.07, 0.93)
	end
	self.frame[unit].normalTexture:SetVertexColor(Gladius.db.trinketGlossColor.r, Gladius.db.trinketGlossColor.g, Gladius.db.trinketGlossColor.b, Gladius.db.trinketGloss and Gladius.db.trinketGlossColor.a or 0)
	-- cooldown
	if (Gladius.db.trinketCooldown) then
		self.frame[unit].cooldown:Show()
	else
		self.frame[unit].cooldown:Hide()
	end
	self.frame[unit].cooldown:SetReverse(Gladius.db.trinketCooldownReverse)
	Gladius:Call(Gladius.modules.Timer, "RegisterTimer", self.frame[unit], Gladius.db.trinketCooldown)
	-- hide
	self.frame[unit]:SetAlpha(0)
end

function Trinket:Show(unit)
	local testing = Gladius.test
	-- show frame
	self.frame[unit]:SetAlpha(1)
	if (Gladius.db.trinketGridStyleIcon) then
		self.frame[unit].texture:SetTexture(LSM:Fetch(LSM.MediaType.STATUSBAR, "minimalist"))
		self.frame[unit].texture:SetVertexColor(Gladius.db.trinketGridStyleIconColor.r, Gladius.db.trinketGridStyleIconColor.g, Gladius.db.trinketGridStyleIconColor.b, Gladius.db.trinketGridStyleIconColor.a)
	else
	local trinketIcon
	if (not testing) then
		if (UnitFactionGroup(unit) == "Horde" and Gladius.db.trinketFaction) then
			trinketIcon = UnitLevel(unit) == 80 and "Interface\\Icons\\INV_Jewelry_Necklace_38" or "Interface\\Icons\\INV_Jewelry_TrinketPVP_02"
		else
			trinketIcon = UnitLevel(unit) == 80 and "Interface\\Icons\\INV_Jewelry_Necklace_37" or "Interface\\Icons\\INV_Jewelry_TrinketPVP_01"
		end
	else
		if (UnitFactionGroup("player") == "Horde" and Gladius.db.trinketFaction) then
			trinketIcon = "Interface\\Icons\\INV_Jewelry_Necklace_38"
		else
			trinketIcon = "Interface\\Icons\\INV_Jewelry_Necklace_37"
		end
	end
	self.frame[unit].texture:SetTexture(trinketIcon)
	if (Gladius.db.trinketIconCrop) then
		self.frame[unit].texture:SetTexCoord(0.07, 0.93, 0.07, 0.93)
	end
	self.frame[unit].texture:SetVertexColor(1, 1, 1, 1)
	end
end

function Trinket:Reset(unit)
	if (not self.frame[unit]) then
		return
	end
	-- reset frame
	local trinketIcon
	if (UnitFactionGroup("player") == "Horde" and Gladius.db.trinketFaction) then
		trinketIcon = "Interface\\Icons\\INV_Jewelry_Necklace_38"
	else
		trinketIcon = "Interface\\Icons\\INV_Jewelry_Necklace_37"
	end
	self.frame[unit].texture:SetTexture(trinketIcon)
	if (Gladius.db.trinketIconCrop) then
		self.frame[unit].texture:SetTexCoord(0.07, 0.93, 0.07, 0.93)
	end
	self.frame[unit]:SetScript("OnUpdate", nil)
	-- reset cooldown
	Gladius:Call(Gladius.modules.Timer, "HideTimer", self.frame[unit])
	-- hide
	self.frame[unit]:SetAlpha(0)
end

function Trinket:Test(unit)
	-- test
	if (unit == "arena1") then
		self:UpdateTrinket(unit, 120)
	end
end

-- Add the announcement toggle
function Trinket:OptionsLoad()
	Gladius.options.args.Announcements.args.general.args.announcements.args.trinket = {
		type = "toggle",
		name = L["Trinket"],
		desc = L["Announces when an enemy uses a PvP trinket."],
		disabled = function() return not Gladius.db.modules[self.name] end,
	}
end

function Trinket:GetOptions()
	return {
		general = {
			type = "group",
			name = L["General"],
			order = 1,
			args = {
				widget = {
					type = "group",
					name = L["Widget"],
					desc = L["Widget settings"],
					inline = true,
					order = 1,
					args = {
						trinketGridStyleIcon = {
							type = "toggle",
							name = L["Trinket Grid Style Icon"],
							desc = L["Toggle trinket grid style icon"],
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							order = 5,
						},
						sep = {
							type = "description",
							name = "",
							width = "full",
							order = 7,
						},
						trinketGridStyleIconColor = {
							type = "color",
							name = L["Trinket Grid Style Icon Color"],
							desc = L["Color of the trinket grid style icon"],
							hasAlpha = true,
							get = function(info)
								return Gladius:GetColorOption(info)
							end,
							set = function(info, r, g, b, a)
								return Gladius:SetColorOption(info, r, g, b, a)
							end,
							disabled = function()
								return not Gladius.dbi.profile.trinketGridStyleIcon or not Gladius.dbi.profile.modules[self.name]
							end,
							order = 10,
						},
						trinketGridStyleIconUsedColor = {
							type = "color",
							name = L["Trinket Grid Style Icon Used Color"],
							desc = L["Color of the trinket grid style icon when it's on cooldown"],
							hasAlpha = true,
							get = function(info)
								return Gladius:GetColorOption(info)
							end,
							set = function(info, r, g, b, a)
								return Gladius:SetColorOption(info, r, g, b, a)
							end,
							disabled = function()
								return not Gladius.dbi.profile.trinketGridStyleIcon or not Gladius.dbi.profile.modules[self.name]
							end,
							order = 12,
						},
						sep1 = {
							type = "description",
							name = "",
							width = "full",
							order = 13,
						},
						trinketCooldown = {
							type = "toggle",
							name = L["Trinket Cooldown Spiral"],
							desc = L["Display the cooldown spiral for important auras"],
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							hidden = function()
								return not Gladius.db.advancedOptions
							end,
							order = 15,
						},
						trinketCooldownReverse = {
							type = "toggle",
							name = L["Trinket Cooldown Reverse"],
							desc = L["Invert the dark/bright part of the cooldown spiral"],
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							hidden = function()
								return not Gladius.db.advancedOptions
							end,
							order = 20,
						},
						sep2 = {
							type = "description",
							name = "",
							width = "full",
							order = 23,
						},
						trinketGloss = {
							type = "toggle",
							name = L["Trinket Gloss"],
							desc = L["Toggle gloss on the trinket icon"],
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							hidden = function()
								return not Gladius.db.advancedOptions
							end,
							order = 25,
						},
						trinketGlossColor = {
							type = "color",
							name = L["Trinket Gloss Color"],
							desc = L["Color of the trinket icon gloss"],
							get = function(info)
								return Gladius:GetColorOption(info)
							end,
							set = function(info, r, g, b, a)
								return Gladius:SetColorOption(info, r, g, b, a)
							end,
							hasAlpha = true,
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							hidden = function()
								return not Gladius.db.advancedOptions
							end,
							order = 30,
						},
						sep3 = {
							type = "description",
							name = "",
							width = "full",
							hidden = function()
								return not Gladius.db.advancedOptions
							end,
							order = 33,
						},
						trinketIconCrop = {
							type = "toggle",
							name = L["Trinket Icon Border Crop"],
							desc = L["Toggle if the borders of the trinket icon should be cropped"],
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							order = 35,
						},
						trinketFaction = {
							type = "toggle",
							name = L["Trinket Icon Faction"],
							desc = L["Toggle if the trinket icon should be changing based on the opponents faction"],
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							order = 40,
						},
						sep3 = {
							type = "description",
							name = "",
							width = "full",
							order = 43,
						},
						trinketFrameLevel = {
							type = "range",
							name = L["Trinket Frame Level"],
							desc = L["Frame level of the trinket"],
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							hidden = function()
								return not Gladius.db.advancedOptions
							end,
							min = 1, max = 5, step = 1,
							width = "double",
							order = 45,
						},
					},
				},
				size = {
					type = "group",
					name = L["Size"],
					desc = L["Size settings"],
					inline = true,
					order = 2,
					args = {
						trinketAdjustSize = {
							type = "toggle",
							name = L["Trinket Adjust Size"],
							desc = L["Adjust trinket size to the frame size"],
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							order = 5,
						},
						trinketSize = {
							type = "range",
							name = L["Trinket Size"],
							desc = L["Size of the trinket"],
							min = 10, max = 100, step = 1,
							disabled = function()
								return Gladius.dbi.profile.trinketAdjustSize or not Gladius.dbi.profile.modules[self.name]
							end,
							order = 10,
						},
					},
				},
				position = {
					type = "group",
					name = L["Position"],
					desc = L["Position settings"],
					inline = true,
					order = 3,
					args = {
						trinketAttachTo = {
							type = "select",
							name = L["Trinket Attach To"],
							desc = L["Attach trinket to the given frame"],
							values = function()
								return Gladius:GetModules(self.name)
							end,
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							arg = "general",
							order = 5,
						},
						trinketPosition = {
							type = "select",
							name = L["Trinket Position"],
							desc = L["Position of the trinket"],
							values={["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
							get = function()
								return strfind(Gladius.db.trinketAnchor, "RIGHT") and "LEFT" or "RIGHT"
							end,
							set = function(info, value)
								if (value == "LEFT") then
									Gladius.db.trinketAnchor = "TOPRIGHT"
									Gladius.db.trinketRelativePoint = "TOPLEFT"
								else
									Gladius.db.trinketAnchor = "TOPLEFT"
									Gladius.db.trinketRelativePoint = "TOPRIGHT"
								end
								Gladius:UpdateFrame(info[1])
							end,
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							hidden = function()
								return Gladius.db.advancedOptions
							end,
							order = 6,
						},
						sep = {
							type = "description",
							name = "",
							width = "full",
							order = 7,
						},
						trinketAnchor = {
							type = "select",
							name = L["Trinket Anchor"],
							desc = L["Anchor of the trinket"],
							values = function()
								return Gladius:GetPositions()
							end,
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							hidden = function()
								return not Gladius.db.advancedOptions
							end,
							order = 10,
						},
						trinketRelativePoint = {
							type = "select",
							name = L["Trinket Relative Point"],
							desc = L["Relative point of the trinket"],
							values = function()
								return Gladius:GetPositions()
							end,
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							hidden = function()
								return not Gladius.db.advancedOptions
							end,
							order = 15,
						},
						sep2 = {
							type = "description",
							name = "",
							width = "full",
							order = 17,
						},
						trinketOffsetX = {
							type = "range",
							name = L["Trinket Offset X"],
							desc = L["X offset of the trinket"],
							min = - 100, max = 100, step = 1,
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							order = 20,
						},
						trinketOffsetY = {
							type = "range",
							name = L["Trinket Offset Y"],
							desc = L["Y offset of the trinket"],
							disabled = function()
								return not Gladius.dbi.profile.modules[self.name]
							end,
							min = - 50, max = 50, step = 1,
							order = 25,
						},
					},
				},
			},
		},
	}
end